package com.exam.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.exam.pojo.domain.ExamHistory;
import com.exam.pojo.domain.Question;
import com.exam.pojo.domain.Ranking;
import com.exam.pojo.domain.User;
import com.exam.pojo.dto.ExamHistoryDTO;
import com.exam.pojo.dto.ExamInfo;
import com.exam.pojo.vo.ExamHistoryVO;
import com.exam.pojo.vo.ExamQuestionVO;
import com.exam.service.IExamHistoryService;
import com.exam.service.IRankingService;
import com.exam.utils.CollUtils;
import com.exam.utils.StringUtils;
import lombok.RequiredArgsConstructor;

import org.bson.types.ObjectId;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ExamHistoryServiceImpl implements IExamHistoryService {
    
    private final MongoTemplate mongoTemplate;
    private final IRankingService rankingService;

    @Override
    public List<ExamHistoryVO> listByUUid(String uuid) {
        Query query = Query.query(Criteria.where("uuid").is(uuid));
        query.with(Sort.by(Sort.Direction.DESC,"rate"));
        List<ExamHistory> examHistoryList = mongoTemplate.find(query, ExamHistory.class);
        if(CollUtils.isNotEmpty(examHistoryList)){
            Map<Long,Question> map = new HashMap<>();
            //组装数据
            Set<Long> qids = new HashSet<>();
            for (ExamHistory history : examHistoryList) {
                List<ExamInfo> examList = history.getExamList();
                if(CollUtils.isNotEmpty(examList)){
                    qids.addAll(CollUtils.getFieldValues(examList,"questionId",Long.class));
                }
            }
            if(CollUtils.isNotEmpty(qids)){
                List<Question> questionList = mongoTemplate.find(Query.query(Criteria.where("id").in(qids)), Question.class);
                //将list-->Map
                map = CollUtils.fieldValueMap(questionList,"id");
                //填充数据
                List<ExamHistoryVO> voList = new ArrayList<>(examHistoryList.size());
                for (ExamHistory history : examHistoryList) {
                    ExamHistoryVO vo = BeanUtil.toBean(history, ExamHistoryVO.class);
                    List<ExamInfo> examList = history.getExamList();
                    List<ExamQuestionVO> questionVOList = new ArrayList<>(examList.size());
                    for (ExamInfo examInfo : examList) {
                        Question question = map.get(examInfo.getQuestionId());
                        String checkSerialKey = examInfo.getCheckSerialKey();
                        questionVOList.add(ExamQuestionVO.of(question,checkSerialKey));
                    }
                    vo.setQuestions(questionVOList);
                    voList.add(vo);
                }
                return voList;
            }
        }
        return CollUtils.emptyList();
    }

    @Override
    public void add(ExamHistoryDTO dto) {
        ExamHistory examHistory = BeanUtil.toBean(dto, ExamHistory.class);
        examHistory.setCreateTime(LocalDateTime.now());
        examHistory.setId(new ObjectId());
        Long correctNum = dto.getCorrectNum();
        Long errorNum = dto.getErrorNum();

        double rate = calcRate(correctNum,errorNum);
        examHistory.setRate(rate);
        if(StringUtils.isNotEmpty(dto.getContent())){
            JSONArray arrays = JSONUtil.parseArray(dto.getContent());
            List<ExamInfo> examInfos = arrays.stream().map(arr -> {
                JSONObject obj = (JSONObject) arr;
                ExamInfo info = new ExamInfo();
                info.setQuestionId(Long.valueOf(obj.getStr("id")));
                info.setCheckSerialKey(obj.getStr("checkSerial"));
                return info;
            }).collect(Collectors.toList());
            examHistory.setExamList(examInfos);
        }
        mongoTemplate.insert(examHistory);
        User user = mongoTemplate.findOne(Query.query(Criteria.where("id").is(dto.getUuid())), User.class);
        if(user!=null){
            Long total = dto.getCorrectNum() + dto.getErrorNum();
            if(total!=null && total.intValue() == 30){
                Ranking ranking = new Ranking();
                ranking.setId(examHistory.getUuid());
                ranking.setNickName(user.getNickname());
                ranking.setHeadImg(user.getHeadImg());
                ranking.setRate(examHistory.getRate());
                ranking.setDuration(examHistory.getDuration());
                ranking.setNums(30);
                rankingService.add(ranking);
            }
            //更新用户集合中的考试信息
            mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(dto.getUuid())),
                    new Update().inc("examNums",1).inc("examRates",examHistory.getRate()),
                    User.class);
        }
    }

    private double calcRate(Long correctNum, Long errorNum){
        if(correctNum == null || errorNum == null || correctNum.intValue() == 0){
            return 0.0;
        }
        BigDecimal fz = new BigDecimal(correctNum.toString());
        Long total = correctNum + errorNum;
        BigDecimal fm = new BigDecimal(total.toString());
        return fz.multiply(new BigDecimal("100")).divide(fm,2, RoundingMode.HALF_UP).doubleValue();
    }
}
